home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 1.iso
/
ARGONET
/
PD
/
FILER
/
TARSRC.SPK
/
c
/
tapeio
< prev
next >
Wrap
Text File
|
1994-08-05
|
14KB
|
589 lines
/* tape input/output routines */
#include <limits.h>
#include <ctype.h>
#include <stdlib.h>
#include "tar.h"
#include "dir.h"
#include "disc.h"
#include "timecon.h"
#include "perms.h"
#include "rmt.h"
#include "tapeio.h"
static long VolFreeSpace;
static int FreeSpace(char *FileName, int InitLen, int InitInc, int WriteMode) {
int FileHandle,reallen,len,inc;
os_error *Error;
os_regset Regs;
do {
do {
Regs.r[0] = WriteMode ? 0x83 : 0xC3;
Regs.r[1] = (int)FileName;
} while (!chkos(os_find(&Regs)));
FileHandle = Regs.r[0];
Regs.r[0] = 6;
Regs.r[1] = FileHandle;
len = InitLen;
reallen = InitLen;
inc = InitInc;
do {
Regs.r[2] = len + inc;
Error = os_args(&Regs);
if (Error == NULL) {
fprintf(stderr,"\rFree Space = %d",reallen);
reallen = Regs.r[2];
len = len + inc;
if (reallen < len)
inc = 0;
} else {
inc = 0;
}
} while (inc > 0);
do {
Regs.r[0] = 0;
Regs.r[1] = FileHandle;
} while (!chkos(os_find(&Regs)));
InitInc /= 4;
InitLen = reallen;
} while (InitInc >= 1024);
if (WriteMode) {
do {
Regs.r[0] = 11;
Regs.r[1] = (int)FileName;
Regs.r[2] = tarFileType;
Regs.r[4] = 0;
Regs.r[5] = reallen;
} while (!chkos(os_swix(OS_File,&Regs)));
}
fprintf(stderr,"\rFree Space = %d\n",reallen);
return reallen;
} /* FreeSpace */
static void WriteDiscHeader(int DiscNo) {
Block_t vblock;
memset(vblock.Block, 0, RECORDSIZE);
vblock.Header.linkflag = LF_VOLHDR;
sprintf(vblock.Header.name,"Volume #%d",DiscNo);
sprintf(vblock.Header.chksum, "%6o", checksum(&vblock));
writetape(vblock.Block);
} /* WriteDiscHeader */
static void OpenArchiveFile(int WriteMode) {
char *mode;
char answer;
if (!WriteMode) {
mode = "rb";
} else {
if (CreateArchive)
mode = "wb";
else
mode = "rb+";
}
while ((ArchiveFD = fopen(ArchiveName, mode)) == NULL) {
fprintf(stderr, "tar: cannot open %s\n", ArchiveName);
if (!QuietExecution) {
fprintf(stderr, "tar: retry? ");
answer = Decision('y');
}
if (QuietExecution || answer == 'n' || answer == 'N') {
Terminate(8);
}
}
ArchiveOpen = 1;
} /* OpenArchiveFile */
static void OpenArchiveRMT(int WriteMode) {
int mode;
char answer;
if (!WriteMode) {
mode = O_RDONLY;
} else {
if (CreateArchive)
mode = O_CREAT | O_WRONLY;
else
mode = O_APPEND | O_RDWR;
}
while ((rmt_fd = rmtopen(ArchiveName,mode,0666)) == NULL) {
fprintf(stderr, "tar: cannot open %s\n", ArchiveName);
if (!QuietExecution) {
fprintf(stderr, "tar: retry? ");
answer = Decision('y');
}
if (QuietExecution || answer == 'n' || answer == 'N') {
Terminate(8);
}
}
ArchiveOpen = 1;
} /* OpenArchiveRMT */
static void NewTape(int WriteMode) {
recno =0;
first = 0;
switch (tapedevice) {
case tapedevice_DISC:
InitDisc();
break;
case tapedevice_FILE:
VolFreeSpace = INT_MAX;
if (MultipleVolumes) {
if (AppendToArchive)
VolFreeSpace = FreeSpace(ArchiveName,0,512000,WriteMode);
else
VolFreeSpace = INT_MAX;
}
OpenArchiveFile(WriteMode);
break;
case tapedevice_RMT:
VolFreeSpace = INT_MAX;
OpenArchiveRMT(WriteMode);
break;
}
} /* NewTape */
static void WriteDiscEnd(int DiscNo) {
Block_t vblock;
memset(vblock.Block, 0, RECORDSIZE);
vblock.Header.linkflag = LF_VOLEND;
sprintf(vblock.Header.name,"Volume #%d",DiscNo);
sprintf(vblock.Header.chksum, "%6o", checksum(&vblock));
writetape(vblock.Block);
} /* WriteDiscEnd */
static int chkchecksum(Block_t *Block) {
int SavedCheckSum;
int CalculatedCheckSum;
sscanf(Block->Header.chksum, "%o", &SavedCheckSum);
CalculatedCheckSum = checksum(Block);
if (SavedCheckSum != CalculatedCheckSum) {
fprintf(stderr, "tar: directory checksum error (%d != %d)\n",
SavedCheckSum, CalculatedCheckSum);
if (IgnoreArchiveErrors) {
return 0;
}
Terminate(9);
}
return(1);
} /* chkchecksum */
static void ReadDiscHeader(int ExpectedDiscNo) {
int ActualDiscNo=0;
int ok;
Block_t vblock;
do {
ok = 1;
if (ExpectedDiscNo > 1) {
fprintf(stderr,"Please insert disc #%d:",ExpectedDiscNo);
while (getchar() != '\n')
;
}
NewTape(0);
readtape(vblock.Block);
chkchecksum(&vblock);
if (vblock.Header.linkflag != LF_VOLHDR) {
fprintf(stderr,"tar: disc header expected\n");
ok = 0;
} else {
sscanf(vblock.Header.name,"Volume #%d",&ActualDiscNo);
if (ActualDiscNo != ExpectedDiscNo) {
fprintf(stderr,"tar: discs out of sequence (disc #%d)\n",ActualDiscNo);
if (ExpectedDiscNo > 1)
ok = 0;
else {
DiscNo = ActualDiscNo;
ok = 1;
}
}
}
} while (!ok);
} /* ReadDiscHeader */
static void ChkDiscEnd(Block_t *vblock, int ExpectedDiscNo) {
int DiscNo=0;
if (vblock->Header.linkflag != LF_VOLEND) {
fprintf(stderr,"tar: disc end expected\n");
return;
}
sscanf(vblock->Header.name,"Volume #%d",&DiscNo);
if (DiscNo != ExpectedDiscNo)
fprintf(stderr,"tar: disc end out of sequence\n");
if (MultipleVolumes && tapedevice == tapedevice_FILE) {
fclose(ArchiveFD);
ArchiveOpen = 0;
}
} /* ChkDiscEnd */
static void NextDisc() {
ChkDiscEnd(&Block,DiscNo++);
ReadDiscHeader(DiscNo);
} /* NextDisc */
void NewDisc() {
WriteDiscEnd(DiscNo++);
flushtape();
os_cli("dismount 0");
fprintf(stderr,"Please insert disc #%d:",DiscNo);
while (getchar() != '\n')
;
if (FormatFloppies && MultipleVolumes && CreateArchive) {
FormatDisc();
}
NewTape(1);
WriteDiscHeader(DiscNo);
} /* NewDisc */
void open_writetape(void) {
char answer;
switch (tapedevice) {
case tapedevice_DISC:
SetupDisc(driveno,format);
if (!NoDiskDestroyConfirmation && !QuietExecution) {
fprintf(stderr,
"tar: warning:\a data on drive %d will be overwritten!\n", driveno);
fprintf(stderr, "tar: continue? ");
answer = Decision('n');
if (answer == 'n' || answer == 'N') {
Terminate(10);
}
}
if (FormatFloppies && MultipleVolumes && CreateArchive) {
FormatDisc();
}
if (MultipleVolumes && CreateArchive) {
WriteDiscHeader(DiscNo);
}
break;
case tapedevice_FILE:
if (FormatFloppies && MultipleVolumes && CreateArchive) {
FormatDisc();
}
if (MultipleVolumes)
VolFreeSpace = FreeSpace(ArchiveName,0,512000,1);
else
VolFreeSpace = INT_MAX;
OpenArchiveFile(1);
if (MultipleVolumes && CreateArchive) {
WriteDiscHeader(DiscNo);
}
break;
case tapedevice_RMT:
VolFreeSpace = INT_MAX;
OpenArchiveRMT(1);
if (MultipleVolumes && CreateArchive) {
WriteDiscHeader(DiscNo);
}
break;
}
} /* open_writetape */
void open_readtape(void) {
switch (tapedevice) {
case tapedevice_DISC:
SetupDisc(driveno,format);
break;
case tapedevice_FILE:
VolFreeSpace = INT_MAX;
OpenArchiveFile(0);
break;
case tapedevice_RMT:
VolFreeSpace = INT_MAX;
OpenArchiveRMT(0);
break;
}
} /* open_readtape */
int checksum(Block_t *Block) {
int i;
char *cp;
for (cp = Block->Header.chksum; cp < &Block->Header.chksum[sizeof(Block->Header.chksum)]; cp++)
*cp = ' ';
i = 0;
for (cp = Block->Block; cp < &Block->Block[RECORDSIZE]; cp++)
i += *cp;
return (i);
} /* checksum */
static int WriteBufferBlocks(char *Buffer, int NumBlocks) {
int Written;
switch (tapedevice) {
case tapedevice_DISC:
return WriteDisc(Buffer, (long)NumBlocks * RECORDSIZE) / RECORDSIZE;
case tapedevice_FILE:
Written = fwrite(Buffer, RECORDSIZE, NumBlocks, ArchiveFD);
if (VolFreeSpace != INT_MAX) {
VolFreeSpace -= (long)Written * (long)RECORDSIZE;
}
return Written;
case tapedevice_RMT:
Written = rmtwrite(rmt_fd, Buffer, NumBlocks * RECORDSIZE);
if (VolFreeSpace != INT_MAX) {
VolFreeSpace -= (long)Written;
}
return Written;
}
return 0;
} /* WriteBufferBlocks */
static int ReadBufferBytes(char *Buffer, int NumBytes) {
int NumRead;
switch (tapedevice) {
case tapedevice_DISC:
return(ReadDisc(Buffer,(long)NumBytes));
case tapedevice_FILE:
NumRead = fread(Buffer, 1, NumBytes, ArchiveFD);
if (VolFreeSpace != INT_MAX) {
VolFreeSpace -= NumRead;
}
return NumRead;
case tapedevice_RMT:
NumRead = rmtread(rmt_fd, Buffer, NumBytes);
if (VolFreeSpace != INT_MAX) {
VolFreeSpace -= NumRead;
}
return NumRead;
}
return 0;
} /* ReadBufferBytes */
void flushtape(void) {
if (recno > 0 && recno < nblock) {
WriteBufferBlocks((char *)TmpBlock,recno);
}
switch (tapedevice) {
case tapedevice_DISC:
FlushDisc();
break;
case tapedevice_FILE:
fclose(ArchiveFD);
SetFileType(ArchiveName, tarFileType);
ArchiveOpen = 0;
break;
case tapedevice_RMT:
rmtclose(rmt_fd);
ArchiveOpen = 0;
break;
}
} /* flushtape */
static void writeblocks() {
if (WriteBufferBlocks((char *)TmpBlock, nblock) < nblock) {
fprintf(stderr, "tar: tape write error\n");
Terminate(11);
}
recno = 0;
} /* writeblocks */
int writetape(char *buffer) {
first = 1;
if (recno >= nblock)
writeblocks();
memcpy((char *)&TmpBlock[recno++], buffer, RECORDSIZE);
if (recno >= nblock)
writeblocks();
return(RECORDSIZE);
} /* writetape */
void putempty(void) {
char buf[RECORDSIZE];
memset(buf, 0, sizeof (buf));
writetape(buf);
} /* putempty */
int endtape(void) {
if (IgnoreArchiveErrors) {
return 0;
}
return (Block.Header.name[0] == '\0');
} /* endtape */
static int bread(char *buf, int size) {
int count;
static int lastread = 0;
if (!Reblock)
return (ReadBufferBytes(buf, size));
for (count = 0; count < size; count += lastread) {
if (lastread < 0) {
if (count > 0)
return (count);
return (lastread);
}
lastread = ReadBufferBytes(buf, size - count);
buf += lastread;
}
return (count);
} /* bread */
int readtape(char *buffer) {
int NumBytesRead;
if (recno >= nblock || first == 0) {
if ((NumBytesRead = bread((char *)TmpBlock, RECORDSIZE*nblock)) <= 0) {
fprintf(stderr, "tar: tape read error\n");
Terminate(12);
}
if ((NumBytesRead % RECORDSIZE) != 0) {
fprintf(stderr, "tar: tape blocksize error\n");
if (first == 0)
Terminate(13);
}
NumBlocksRead = NumBytesRead/RECORDSIZE;
if (first == 0) {
if (NumBlocksRead != nblock) {
fprintf(stderr, "tar: blocksize = %d\n", NumBlocksRead);
nblock = NumBlocksRead;
}
}
recno = 0;
}
first = 1;
memcpy(buffer, (char *)&TmpBlock[recno++], RECORDSIZE);
return (RECORDSIZE);
} /* readtape */
void backtape(void) {
recno--;
switch (tapedevice) {
case tapedevice_DISC:
BackDisc();
break;
case tapedevice_FILE:
fseek(ArchiveFD, -(long)RECORDSIZE * NumBlocksRead, SEEK_CUR);
break;
case tapedevice_RMT:
rmtlseek(rmt_fd,-(long)RECORDSIZE * NumBlocksRead, SEEK_CUR);
break;
}
} /* backtape */
void passtape(long Length) {
long blocks;
char buf[RECORDSIZE];
if (Block.Header.linkflag == '1')
return;
blocks = Length;
blocks += RECORDSIZE-1;
blocks /= RECORDSIZE;
while (!UserInterrupt && blocks-- > 0)
readtape(buf);
} /* passtape */
void getdir(CatInfo *InfoBlk) {
int mode, NameLen, FileType;
int ThisDiscNo;
long mtime;
top:
readtape((char *)&Block);
if (Block.Header.name[0] == 0) {
if (IgnoreArchiveErrors) {
goto top;
} else {
return;
}
}
if (!chkchecksum(&Block))
goto top;
if (Block.Header.linkflag == LF_VOLEND) {
if (MultipleVolumes) {
NextDisc();
} else {
fprintf(stderr,"tar: unexpected end of disc\n");
Terminate(14);
}
return;
}
if (Block.Header.linkflag == LF_VOLHDR) {
sscanf(Block.Header.name,"Volume #%d",&ThisDiscNo);
if (ThisDiscNo != 1) {
fprintf(stderr,"tar: unexpected disc header (disc #%d)\n",ThisDiscNo);
DiscNo = ThisDiscNo;
return;
}
MultipleVolumes = 1;
return;
}
memset((char *)InfoBlk,0,sizeof(CatInfo));
sscanf(Block.Header.size, "%lo", &InfoBlk->Length);
if (isArchie = (strcmp(Block.Header.magic, ARC_MAGIC) == 0), isArchie) {
sscanf(Block.Header.LoadAddress, "%lo", &InfoBlk->LoadAddress);
sscanf(Block.Header.ExecAddress, "%lo", &InfoBlk->ExecAddress);
sscanf(Block.Header.Attr, "%lo", &InfoBlk->Attr);
sscanf(Block.Header.Date,"%x %lx",&InfoBlk->DateAndName[4],&InfoBlk->DateAndName);
} else {
sscanf(Block.Header.mode,"%o",&mode);
InfoBlk->Attr = unix_to_fs_perms(mode);
if (CommaFileTypes && (NameLen = strlen(Block.Header.name)) > 4 &&
Block.Header.name[NameLen - 4] == ',' &&
isxdigit(Block.Header.name[NameLen - 3]) &&
isxdigit(Block.Header.name[NameLen - 2]) &&
isxdigit(Block.Header.name[NameLen - 1])) {
FileType = (int)strtoul(Block.Header.name + NameLen - 3, NULL, 16);
Block.Header.name[NameLen - 4] = 0;
} else {
FileType = (mode & (XOWN | XOTH | XGRP)) ? ft_Absolute : ft_Text;
}
InfoBlk->LoadAddress = 0xFFF00000L | ((long)FileType << 8);
sscanf(Block.Header.mtime,"%lo",&mtime);
unix_to_fs_time((unsigned char *)&InfoBlk->DateAndName,mtime);
InfoBlk->ExecAddress = *(long *)&InfoBlk->DateAndName;
InfoBlk->LoadAddress |= InfoBlk->DateAndName[4];
}
if (Block.Header.compressed == CF_COMPRESSED)
sscanf(Block.Header.compression,"%o",&compression);
} /* getdir */
long FreeOnTape(void) {
return (tapedevice == tapedevice_DISC ? FreeOnDisc() : VolFreeSpace) -
(long)recno * (long)RECORDSIZE;
} /* FreeOnTape */